package com.jyw.router.hospital.service.impl;

import java.util.List;
import java.util.concurrent.TimeUnit;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jyw.router.common.core.domain.CommonResult;
import com.jyw.router.common.core.redis.RedisCache;
import com.jyw.router.common.exception.ServiceException;
import com.jyw.router.common.exception.constant.ExceptionCodeConstant;
import com.jyw.router.common.utils.DateUtils;
import com.jyw.router.common.utils.StringUtils;
import com.jyw.router.hospital.domain.HospitalInfo;
import com.jyw.router.hospital.domain.HospitalRegisterUser;
import com.jyw.router.hospital.domain.dto.UserTokenRedisDto;
import com.jyw.router.hospital.domain.vo.LoginMiniappVo;
import com.jyw.router.hospital.service.IHospitalInfoService;
import com.jyw.router.hospital.service.IHospitalRegisterUserService;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.jyw.router.hospital.mapper.WxUserMapper;
import com.jyw.router.hospital.domain.WxUser;
import com.jyw.router.hospital.service.IWxUserService;

import javax.annotation.Resource;

import static com.jyw.router.common.core.redis.RedisKeyConstant.USER_TOKEN;

/**
 * 微信用户信息Service业务层处理
 * 
 * @author shenjun
 * @date 2023-04-19
 */
@Service
@Slf4j
public class WxUserServiceImpl extends ServiceImpl<WxUserMapper,WxUser> implements IWxUserService
{
    @Autowired
    private WxUserMapper wxUserMapper;

    @Resource
    private IHospitalInfoService hospitalService;

    @Resource
    private RedisCache redisCache;

    /**
     * 查询微信用户信息
     * 
     * @param id 微信用户信息主键
     * @return 微信用户信息
     */
    @Override
    public WxUser selectWxUserById(Long id)
    {
        return wxUserMapper.selectWxUserById(id);
    }

    /**
     * 查询微信用户信息列表
     * 
     * @param wxUser 微信用户信息
     * @return 微信用户信息
     */
    @Override
    public List<WxUser> selectWxUserList(WxUser wxUser)
    {
        return wxUserMapper.selectWxUserList(wxUser);
    }

    /**
     * 新增微信用户信息
     * 
     * @param wxUser 微信用户信息
     * @return 结果
     */
    @Override
    public int insertWxUser(WxUser wxUser)
    {
        wxUser.setCreateTime(DateUtils.getNowDate());
        return wxUserMapper.insertWxUser(wxUser);
    }

    /**
     * 修改微信用户信息
     * 
     * @param wxUser 微信用户信息
     * @return 结果
     */
    @Override
    public int updateWxUser(WxUser wxUser)
    {
        wxUser.setUpdateTime(DateUtils.getNowDate());
        return wxUserMapper.updateWxUser(wxUser);
    }

    /**
     * 批量删除微信用户信息
     * 
     * @param ids 需要删除的微信用户信息主键
     * @return 结果
     */
    @Override
    public int deleteWxUserByIds(Long[] ids)
    {
        return wxUserMapper.deleteWxUserByIds(ids);
    }

    /**
     * 删除微信用户信息信息
     * 
     * @param id 微信用户信息主键
     * @return 结果
     */
    @Override
    public int deleteWxUserById(Long id)
    {
        return wxUserMapper.deleteWxUserById(id);
    }

    @Override
    public void registerMp(WxMpUser wxMpUser) {
        //判断是否存在unionId数据
        WxUser wxUser = getUserByUnionId(wxMpUser.getUnionId());
        //用户没有数据
        if(ObjectUtils.isEmpty(wxUser)){
            //新建用户
            wxUser = new WxUser(wxMpUser);
            save(wxUser);
        }else{
            //注入公众号信息
            wxUser.setMpInfo(wxMpUser);
        }
    }


    @Override
    public CommonResult login(LoginMiniappVo loginVo) {
        //通过unionId获取数据库中是否存在用户信息
        WxUser wxUser = getUserByMiniappOpenId(loginVo.getOpenId());
        //如果用户信息不存在
        if(ObjectUtils.isEmpty(wxUser)){
//            用户未传入手机号,通知绑定手机号
            if(StringUtils.isEmpty(loginVo.getPhone())&&StringUtils.isEmpty(loginVo.getHospitalId())){
                throw new ServiceException("请绑定手机号", ExceptionCodeConstant.NOT_BIND_PHONE);
            }
            //传入了手机号注册用户数据
            wxUser = registerWxUser(loginVo);
        }
        //如果用户信息存在,那么判断是否存在医院注册信息
        return hospitalService.login(wxUser, loginVo.getHospitalId(),loginVo);
    }

    /**
     * 通过unionId获取用户信息
     * @param unionId
     * @return
     */
    private WxUser getUserByUnionId(String unionId){
        LambdaQueryWrapper<WxUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WxUser::getUnionId,unionId);
        return getOne(queryWrapper);
    }

    /**
     * 通过小程序唯一标识获取用户信息
     * @param openId
     * @return
     */
    @Override
    public WxUser getUserByMiniappOpenId(String openId){
        LambdaQueryWrapper<WxUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WxUser::getMiniappOpenId,openId);
        return getOne(queryWrapper);
    }

    @Override
    public WxUser getUserByMpOpenId(String openId) {
        LambdaQueryWrapper<WxUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WxUser::getMpOpentId,openId);
        return getOne(queryWrapper);
    }

    @Override
    public void unsubscribe(String openId) {
        WxUser wxUser = getUserByMpOpenId(openId);
        if(ObjectUtils.isEmpty(wxUser)){
            log.error("取消关注,无法通过公众号唯一标识,查找用户:{}",openId);
        }
        //设置关注为未关注
        wxUser.unsubscribe();
        updateById(wxUser);
    }

    @Override
    public WxUser registerMiniApp(LoginMiniappVo loginVo) {
        //  用户未传入手机号,通知绑定手机号
        if(StringUtils.isEmpty(loginVo.getPhone())){
            throw new ServiceException("请绑定手机号", ExceptionCodeConstant.NOT_BIND_PHONE);
        }
        //传入了手机号注册用户数据
        WxUser wxUser = registerWxUser(loginVo);
        return wxUser;
    }

    @Override
    public UserTokenRedisDto getUserByToken(String token) {
        UserTokenRedisDto dto = redisCache.getCacheObject(USER_TOKEN + token);
        if(ObjectUtils.isEmpty(dto)){
            LambdaQueryWrapper<WxUser> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(WxUser::getToken,token);
            WxUser wxUser = getOne(queryWrapper);
            if(ObjectUtils.isEmpty(wxUser)){
                throw new ServiceException("token已失效,请重新登录",ExceptionCodeConstant.TOKEN_UNAUTHORIZED);
            }
            dto = new UserTokenRedisDto(wxUser);
            redisCache.setCacheObject(USER_TOKEN+token,dto,30, TimeUnit.DAYS);
        }
        return dto;
    }

    @Override
    public WxUser getUserByPhone(String phone) {
        LambdaQueryWrapper<WxUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WxUser::getPhone,phone);
        queryWrapper.orderByDesc(WxUser::getCreateTime);
        List<WxUser> list = list(queryWrapper);
        if(list.size()>0){
            return list.get(0);
        }
        return null;
    }

    /**
     * 微信小程序注册用户
     * @param loginVO
     * @return
     */
    private WxUser registerWxUser(LoginMiniappVo loginVO){
        //通过unionId获取用户
        WxUser wxUser = getUserByUnionId(loginVO.getUnionId());
        if(ObjectUtils.isEmpty(wxUser)){
            //用户不存在,新建用户信息
            wxUser = loginVO.buildWxUser();
            save(wxUser);
        }else{
            //赋值小程序信息到用户上
            wxUser.setMiniInfo(loginVO);
            updateById(wxUser);
        }
        return wxUser;
    }
}
